#include "dialog.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QMatrix>

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    label1 = new QLabel;
    image1.load(":/images/image.jpg");
    label1->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    label1->setPixmap(QPixmap::fromImage(image1));

    label2 = new QLabel;
    image2.load(":/images/image.jpg");
    label2->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    label2->setPixmap(QPixmap::fromImage(image2));

    label3 = new QLabel;
    image3.load(":/images/image.jpg");
    label3->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    label3->setPixmap(QPixmap::fromImage(image3));

    stateLabel = new QLabel(tr("鼠标按下标志"));
    stateLabel->setAlignment(Qt::AlignHCenter);

    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(label1);
    layout->addWidget(label2);
    layout->addWidget(label3);

    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->addLayout(layout);
    mainLayout->addWidget(stateLabel);

    // 安装事件过滤器
    label1->installEventFilter(this);
    label2->installEventFilter(this);
    label3->installEventFilter(this);
}

Dialog::~Dialog()
{

}

bool Dialog::eventFilter(QObject *watched, QEvent *event) // 返回true告诉QT不用再继续处理了，返回false则QT还会继续处理
{
    if (watched == label1) // 判断当前发生事件的对象
    {
        if (event->type() == QEvent::MouseButtonPress) // 鼠标按下
        {
            QMouseEvent *mouseEvent = (QMouseEvent*) event;

            if (mouseEvent->buttons() & Qt::LeftButton)
            {
                stateLabel->setText(tr("左键按下左边图片"));
            }
            else if (mouseEvent->buttons() & Qt::MidButton)
            {
                stateLabel->setText(tr("中键按下左边图片"));
            }
            else if (mouseEvent->buttons() & Qt::RightButton)
            {
                stateLabel->setText(tr("右键按下左边图片"));
            }

            // 显示放大的图片
            QMatrix matrix;
            matrix.scale(1.5, 1.5);
            QImage tmp = image1.transformed(matrix);
            label1->setPixmap(QPixmap::fromImage(tmp));
        }

        // 释放鼠标事件，恢复图片大小
        if (event->type() == QEvent::MouseButtonRelease)
        {
            stateLabel->setText(tr("鼠标释放左边图片"));
            label1->setPixmap(QPixmap::fromImage(image1));
        }
    }

    // 将其他的事件交给基类处理
    return QDialog::eventFilter(watched, event);
}

//当一个事件产生时，Qt 通过实例化一个 QEvent 的合适的子类来表示它，然后通过调用 event() 函数发送给 QObject 的实例（或者它的子类）。
//event() 函数本身并不会处理事件，根据事件类型，它将调用相应的事件处理函数，并且返回事件被接受还是被忽略。
//每一个事件都有其相关联的类型，由 QEvent::Type 定义。
//通常事件的处理需要调用一个虚函数。如果你在自己的函数中并不打算实现所有的处理，你可以调用基类的实现。

//Qt提供5个级别的事件处理和过滤：
//1，重新实现事件函数。 比如： mousePressEvent(), keyPress-Event(), paintEvent() 。
//这是最常规的事件处理方法。
//2，重新实现QObject::event().
//这一般用在Qt没有提供该事件的处理函数时。也就是，我们增加新的事件时。
//3，安装事件过滤器
//4，在 QApplication 上安装事件过滤器。
//这之所以被单独列出来是因为： QApplication 上的事件过滤器将捕获应用程序的所有事件，而且第一个获得该事件。也就是说事件在发送给其它任何一个event filter之前发送给QApplication的event filter。
//5，重新实现QApplication 的 notify()方法.
//Qt使用 notify()来分发事件。要想在任何事件处理器捕获事件之前捕获事件，唯一的方法就是重新实现QApplication 的 notify()方法。

//virtual bool QObject::eventFilter ( QObject * watched, QEvent * event )
//如果watched对象安装了事件过滤器，这个函数会被调用并进行事件过滤，然后才轮到watched组件进行事件处理。在重写这个函数时，如果你需要过滤掉某个事件，例如停止对这个事件的响应，需要返回true

//void QObject::installEventFilter ( QObject * filterObj )
//这个函数是QObject的一个函数，因此可以安装到任何QObject的子类，并不仅仅是UI组件。这个函数接收一个QObject对象，调用了这个函数安装事件过滤器的组件会调用filterObj定义的eventFilter()函数。例如，textField.installEventFilter(obj)，则如果有事件发送到textField组件是，会先调用obj->eventFilter()函数，然后才会调用textField.event()。

//如果一个组件安装了多个过滤器，则最后一个安装的会最先调用，类似于堆栈的行为。

//事件过滤器和被安装的组件必须在同一线程，否则，过滤器不起作用。另外，如果在install之后，这两个组件到了不同的线程，那么，只有等到二者重新回到同一线程的时候过滤器才会有效。
